import axios from 'axios';
import {AxiosRequestHeaders} from 'axios';
import {useRouter} from 'vue-router';
import {inject} from 'vue';
import Cache from './Cache';
import toast from './Toast';

const cache = new Cache(), router = useRouter();
//设置发送请求的格式
axios.defaults.headers.post["Content-Type"] = "application/json;charset=UTF-8";
//设置超时
axios.defaults.timeout = 300000;
// 请求拦截
axios.interceptors.request.use(
  config => {
    let token;
    if ((token = cache.get('token'))) {
      (config.headers as AxiosRequestHeaders).Authorization = token;
    }
    return config;
  },
  error => {
    return Promise.reject(error);
  }
);
// 响应拦截
axios.interceptors.response.use(
  response => {
    if (response && response.status === 200) {
      let code;
      // 保存 token
      if (response.headers['authorization']) {
        cache.set('token', response.headers.authorization);
      }
      if (!(code = response.data.code)) {
        return Promise.resolve(response);
      } else if (code !== 0) {
        let msg;
        if ((msg = response.data.msg) === '没有权限' || code === -502) {
          const reload: (() => (void | undefined)) | undefined = inject('reload');
          msg = '请登陆后重试';
          cache.removes(['token', 'userMsg']);
          location.reload();
          /*          router.push({
                      path: '/',
                    });*/
        }
        toast.error('请求失败', msg, 3000);
        return Promise.reject(response.data);
      }
      return Promise.resolve(response);
    }
    return Promise.resolve(response);
  },
  error => {
    return Promise.reject(error);
  }
);

function requestMethod(url: string, method: any, data: any) {
  if (method === 'restful') {
    url = url + '/' + data;
    method = 'get';
  }
  return new Promise((resolve, reject) => {
    axios({
      method: method,
      url,
      data: data,
    })
      .then(res => {
        if (res.data) resolve(res.data);
        else resolve(res);
      })
      .catch(err => {
        reject(err)
      })
  })
}

abstract class Request {
  abstract option(url: string, data: any): Promise<any>;

  abstract get(url: string, data?: any): Promise<any>;

  abstract post(url: string, data?: any): Promise<any>;

  abstract put(url: string, data?: any): Promise<any>;

  abstract head(url: string, data?: any): Promise<any>;

  abstract delete(url: string, data?: any): Promise<any>;

  abstract trace(url: string, data?: any): Promise<any>;

  abstract connect(url: string, data?: any): Promise<any>;

  abstract restful(url: string, data?: string[] | number[]): Promise<any>;

  abstract form(url: string, data?: FormData): Promise<any>;
}

const request: Request = {
  option: (url: string, data?: any) => requestMethod(url, 'option', data),
  get: (url: string, data?: any) => new Promise((resolve, reject) => {
    axios({
      method: 'get',
      url,
      params: data,
    })
      .then(res => {
        if (res.data) resolve(res.data);
        else resolve(res);
      })
      .catch(err => {
        reject(err)
      })
  }),
  post: (url: string, data?: any) => requestMethod(url, 'post', data),
  put: (url: string, data?: any) => requestMethod(url, 'put', data),
  head: (url: string, data?: any) => requestMethod(url, 'head', data),
  delete: (url: string, data?: any) => requestMethod(url, 'delete', data),
  trace: (url: string, data?: any) => requestMethod(url, 'trace', data),
  connect: (url: string, data?: any) => requestMethod(url, 'connect', data),
  restful: (url: string, data: string[] | number[]) => {
    if (data.length > 0) {
      for (let dt of data) {
        url += '/' + dt;
      }
    }
    return new Promise((resolve, reject) => {
      axios({
        method: 'get',
        url
      })
        .then(res => {
          if (res.data) resolve(res.data);
          else resolve(res);
        })
        .catch(err => {
          reject(err)
        })
    })
  },
  form: (url: string, data: FormData) => {
    return new Promise((resolve, reject) => {
      axios({
        method: 'post',
        data,
        headers: {
          'Content-Type': 'multipart/form-data'
        },
        url
      })
        .then(res => {
          if (res.data) resolve(res.data);
          else resolve(res);
        })
        .catch(err => {
          reject(err)
        })
    })
  }
}


export default request;